// 版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 支持内存消毒器。请参阅runtime/cgo/mmap.go。

// go:build（linux&&amd64）| |（linux&&arm64）
// /+build linux，amd64 linux，arm64 

package runtime

import "unsafe"

// /\u cgo_mmap在链接到
// /程序时由runtime/cgo填写，因此在使用cgo时仅为非零。
// go:linkname(u cgo_mmap)(u cgo_mmap)
var _cgo_mmap unsafe.Pointer

// (u cgo_munmap)在链接到
// 程序时由runtime/cgo填写,因此使用cgo时仅为非零。
// go:linkname(u cgo)munmap(u cgo)cgo(u munmap)
var _cgo_munmap unsafe.Pointer

// mmap用于在使用cgo时通过C代码将mmap系统调用路由到
// 支持消毒剂拦截器。不允许堆栈拆分，因为此函数
// （由sysAlloc使用）在运行时的许多低级部分被调用，而
// 调用方通常认为它不会获得任何锁。
// go:nosplit 
func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) {
	if _cgo_mmap != nil {
		// 生成ret uintptr，以便在
		// 函数literal中对其进行写入不会触发写入障碍。
		// 此处的写入障碍可能会被打破，因为mmap使用相同的值作为指针和错误值。
		var ret uintptr
		systemstack(func() {
			ret = callCgoMmap(addr, n, prot, flags, fd, off)
		})
		if ret < 4096 {
			return nil, int(ret)
		}
		return unsafe.Pointer(ret), 0
	}
	return sysMmap(addr, n, prot, flags, fd, off)
}

func munmap(addr unsafe.Pointer, n uintptr) {
	if _cgo_munmap != nil {
		systemstack(func() { callCgoMunmap(addr, n) })
		return
	}
	sysMunmap(addr, n)
}

// sysMmap调用mmap系统调用。它是在汇编中实现的。
func sysMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (p unsafe.Pointer, err int)

// callCgoMmap使用GCC调用约定调用运行时/cgo包中的mmap函数。它是在汇编中实现的。
func callCgoMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) uintptr

// sysMunmap调用munmap系统调用。它是在汇编中实现的。
func sysMunmap(addr unsafe.Pointer, n uintptr)

// callCgoMunmap使用GCC调用约定调用运行时/cgo包
// 中的munmap函数。它是在汇编中实现的。
func callCgoMunmap(addr unsafe.Pointer, n uintptr)
